const express = require('express');
const app = express();
const https = require('https');
const fs = require('fs');
const IO = require('socket.io');
const mysql = require('mysql');
const connection = mysql.createConnection({
  host: 'xunzhishimin.site',
  user: 'root',
  password: 'taiZHImin123456',
  database: 'facetime',
});
//执行创建连接
connection.connect();

const options = {
  key: fs.readFileSync('./ssl/214777430070544.key'),
  cert: fs.readFileSync('./ssl/214777430070544.pem'),
  passphrase: 'taiZHImin123456',
};

app.use(express.static('dist'));

const server = https.createServer(options, app).listen(8080);
console.log('The HTTPS server is up and running');

const io = IO(server);
console.log('Socket Secure server is up and running.');

// 所有用户名单
const allUsers = {};
// 所有客户端
const allSockets = {};

io.on('connect', function(socket) {
  let username = ''; //当前登录用户名
  let password = '';//密码
  socket.on('message', function(data) {
    const d = JSON.parse(data);
    switch (d.event) {
      //当有新用户加入时
      case 'join':
        username = d.username;
        password = d.password;
        const sql = 'SELECT password FROM user where username = ' + username;
        const r = connection.query(sql, function(err, result) {
          if (err) {
            return '';
          }
          return result;
        });
        if (r !== password) {
          sendTo(socket, {
            event: 'join',
            message: '密码错误',
            success: false,
          });
        }
        //当昵称重复时
        if (allUsers[user]) {
          sendTo(socket, {
            event: 'join',
            message: '该用户已经登录',
            success: false,
          });
        } else {
          console.log('User joined', data.name);
          //保存用户信息
          allUsers[user] = true; //true表示未通话，false表示正在通话
          allSockets[user] = socket;
          socket.name = user;
          showUserInfo(allUsers);
          sendTo(socket, {
            event: 'join',
            allUsers: allUsers,
            success: true,
          });
        }
        break;

      case 'call':
        let conn = allSockets[data.connectedUser];
        sendTo(conn, {
          event: 'call',
          name: socket.name,
        });
        break;

      case 'offer':
        //for example: UserA wants to call UserB
        console.log('Sending offer to: ', data.connectedUser);
        //if UserB exists then send him offer details
        conn = allSockets[data.connectedUser];
        allUsers[user] = false;
        if (conn != null) {
          showUserInfo(allUsers);
          //setting that UserA connected with UserB
          socket.otherName = data.connectedUser;
          sendTo(conn, {
            event: 'offer',
            offer: data.offer,
            name: socket.name,
          });
        } else {
          sendTo(socket, {
            event: 'msg',
            message: 'Not found this name',
          });
        }
        break;

      case 'accept':
        conn = allSockets[data.connectedUser];
        if (conn != null) {
          if (data.accept) {
            sendTo(conn, {
              event: 'accept',
              accept: true,
            });
          } else {
            allUsers[data.connectedUser] = true;
            sendTo(conn, {
              event: 'accept',
              accept: false,
            });
          }
        }
        break;

      case 'answer':
        console.log('Sending answer to: ', data.connectedUser);
        //for ex. UserB answers UserA
        conn = allSockets[data.connectedUser];
        allUsers[user] = false;
        if (conn != null) {
          showUserInfo(allUsers);
          socket.otherName = data.connectedUser;
          sendTo(conn, {
            event: 'answer',
            answer: data.answer,
          });
        }
        break;

      case 'candidate':
        console.log('Sending candidate to:', data.connectedUser);
        const conn1 = allSockets[data.connectedUser];
        const conn2 = allSockets[socket.otherName];
        if (conn1 != null) {
          sendTo(conn1, {
            event: 'candidate',
            candidate: data.candidate,
          });
        } else {
          sendTo(conn2, {
            event: 'candidate',
            candidate: data.candidate,
          });
        }
        break;

      case 'leave':
        console.log('Disconnecting from', data.connectedUser);
        conn = allSockets[data.connectedUser];
        allUsers[socket.name] = true;
        allUsers[data.connectedUser] = true;
        socket.otherName = null;
        //notify the other user so he can disconnect his peer connection
        if (conn != null) {
          showUserInfo(allUsers);
          sendTo(conn, {
            event: 'leave',
          });
        }
        break;
    }
  });

  socket.on('disconnect', function() {
    if (socket.name) {
      delete allUsers[socket.name];
      delete allSockets[socket.name];
      showUserInfo(allUsers);
      if (socket.otherName) {
        console.log('Disconnecting from ', socket.otherName);
        const conn = allSockets[socket.otherName];
        allUsers[socket.otherName] = true;
        socket.otherName = null;
        if (conn != null) {
          sendTo(conn, {
            type: 'leave',
          });
        }
      }
    }
  });
});

function showUserInfo(allUsers) {
  sendTo(io, {
    event: 'show',
    allUsers: allUsers,
  });
}

function sendTo(connection, message) {
  connection.send(message);
}
